#pragma once

#include <interface/msg/event.hpp>
#include <interface/msg/images.hpp>
#include <interface/msg/lane_points.hpp>
#include <interface/msg/multi_lane_points.hpp>
#include <interface/msg/objects.hpp>

#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <visualization_msgs/msg/marker.hpp>
#include <visualization_msgs/msg/marker_array.hpp>

namespace ui {

class DataProxy : public rclcpp::Node {
    enum class AlarmVehicleLevel {
        SEVERITY = 0,
        WARNING = 1,
        NOTIFY = 2
    };

    typedef struct ObjectModelInfo {
        std::string resource;
        double scaleX { 1.0 };
        double scaleY { 1.0 };
        double scaleZ { 1.0 };

        double eulerX { 0.0 };
        double eulerY { 0.0 };
        double eulerZ { 0.0 };

        double x { 0.0 };
        double y { 0.0 };
        double z { 0.0 };

        double r { 80 / 255.0 };
        double g { 86 / 255.0 };
        double b { 98 / 255.0 };
        double a { 1.0f };

        int32_t lifetimeSec { 1 };
        int32_t lifetimeNsec { 0 };
    } ObjectModelInfo;

public:
    DataProxy(std::string name);

private:
    void onImages(std::shared_ptr<interface::msg::Images> msg);
    void onCameraFusedImages(std::shared_ptr<interface::msg::Images> msg);
    void onCameraFusedObjects(std::shared_ptr<interface::msg::Objects> msg);
    void onMultiFusedObjects(std::shared_ptr<interface::msg::Objects> msg);
    void onLanePoints(std::shared_ptr<interface::msg::MultiLanePoints> msg);
    void onEvent(std::shared_ptr<interface::msg::Event> msg);

    void drawMainCar(void);

    visualization_msgs::msg::MarkerArray objectsToMarkerArray(std::shared_ptr<interface::msg::Objects>, bool isAddCLeanMarker = true);
    std::shared_ptr<AlarmVehicleLevel> isAlarmVehicle(int64_t id);
    ObjectModelInfo getObjectModelInfo(int32_t type);
    void decorateAlarmVehicle(ObjectModelInfo& objectModelInfo, AlarmVehicleLevel alarmVehicleLevel);
    void updateAlarmVehicleMap(void);
    void cleanLastMultiFusedForUi(visualization_msgs::msg::MarkerArray&, std::shared_ptr<interface::msg::Objects>);
    void addCleanMarker(visualization_msgs::msg::MarkerArray& markerArray);

private:
    std::shared_ptr<rclcpp::Subscription<interface::msg::Images>> imagesSubscriber_;
    std::shared_ptr<rclcpp::Subscription<interface::msg::Images>> cameraFusedImagesSubscriber_;
    std::shared_ptr<rclcpp::Subscription<interface::msg::Objects>> cameraFusedSubscriber_;
    std::shared_ptr<rclcpp::Subscription<interface::msg::Objects>> radarFusedSubscriber_ { nullptr };
    std::shared_ptr<rclcpp::Subscription<interface::msg::Objects>> multiFusedSubscriber_ { nullptr };
    std::shared_ptr<rclcpp::Subscription<interface::msg::Event>> eventSubscriber_ { nullptr };
    std::shared_ptr<rclcpp::Subscription<interface::msg::MultiLanePoints>> multiLanePointsSubscriber_ { nullptr };

    std::unordered_map<std::string, std::shared_ptr<rclcpp::Publisher<sensor_msgs::msg::Image>>> uiImagePainters_;
    std::unordered_map<std::string, std::shared_ptr<rclcpp::Publisher<sensor_msgs::msg::Image>>> uiCameraFusedImagePainters_;
    std::shared_ptr<rclcpp::Publisher<visualization_msgs::msg::MarkerArray>> uiCameraFusedObjectPainter_;
    std::shared_ptr<rclcpp::Publisher<visualization_msgs::msg::MarkerArray>> uiMultiFusedObjectPainter_;
    std::shared_ptr<rclcpp::Publisher<visualization_msgs::msg::MarkerArray>> uiLanePainter_;
    std::shared_ptr<rclcpp::Publisher<visualization_msgs::msg::MarkerArray>> uiMasterObjectPainter_;
    std::shared_ptr<rclcpp::TimerBase> timer_;

    std::mutex alarmVehicleMapLock_;
    std::unordered_map<int64_t, std::pair<AlarmVehicleLevel, int64_t>> alarmVehicleMap_;
    // key:id,value:ns
    std::unordered_map<int64_t, std::string> lastIds_;
};
}